package com.cloudjan.codebuilder.controller;

import com.cloudjan.codebuilder.entity.ColumnClass;
import com.cloudjan.codebuilder.entity.DBConfig;
import com.cloudjan.codebuilder.entity.Result;
import com.cloudjan.codebuilder.entity.TableClass;
import com.cloudjan.codebuilder.util.CodeBuilderUtils;
import com.google.common.base.CaseFormat;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 代码构建
 */
@RestController
@RequestMapping("/api/builder/")
public class CodeBuilderController {

    Configuration cfg = null;
    {
        cfg = new Configuration(Configuration.VERSION_2_3_0);
        cfg.setTemplateLoader(new ClassTemplateLoader(CodeBuilderController.class,"/templates"));
        cfg.setDefaultEncoding("UTF-8");
    }

    /**
     * 创建MySQL连接
     * @param map
     * @return
     * @throws Exception
     */
    @PostMapping("/connect")
    public Result connect(@RequestBody Map<String, String> map) throws Exception{
        String packageName = map.get("packageName");
        DBConfig dbConfig = new DBConfig(map.get("url"), map.get("userName"), map.get("password"));
        Connection connection = CodeBuilderUtils.init(dbConfig);
        if (connection == null) {
            return Result.fail("链接数据库失败！");
        }
        DatabaseMetaData metaData = connection.getMetaData();
        ResultSet tables = metaData.getTables(connection.getCatalog(), null, null, null);
        List<TableClass> tableClassList = new ArrayList<>();
        while (tables.next()) {
            TableClass tableClass = new TableClass();
            String tableName = tables.getString("TABLE_NAME");
            String modelName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            tableClass.setTableName(tableName);
            tableClass.setControllerName(modelName + "Controller");
            tableClass.setMapperName(modelName + "Mapper");
            tableClass.setServiceName(modelName+"Service");
            tableClass.setEntityName(modelName+"Entity");
            tableClassList.add(tableClass);
        }
        return Result.ok("连接成功",tableClassList);
    }

    /**
     * 构建代码
     * @return
     */
    @PostMapping("/build")
    public Result build(String packageName,HttpServletRequest request) throws Exception{
        Template entityTemplate = cfg.getTemplate("Entity.java.ftl");
        Connection connection = CodeBuilderUtils.getConnection();
        DatabaseMetaData metaData = connection.getMetaData();
        String catalog = connection.getCatalog();
        ResultSet tables = metaData.getTables(connection.getCatalog(), null, null, null);
        while (tables.next()) {
            TableClass tableClass = new TableClass();
            tableClass.setPackageName(packageName);
            String tableName = tables.getString("TABLE_NAME");
            String modelName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
            tableClass.setTableName(tableName);
            tableClass.setControllerName(modelName + "Controller");
            tableClass.setMapperName(modelName + "Mapper");
            tableClass.setServiceName(modelName+"Service");
            tableClass.setEntityName(modelName+"Entity");
            ResultSet columns = metaData.getColumns(catalog, null, null, null);
            ResultSet primaryKeys = metaData.getPrimaryKeys(catalog, null, tableClass.getTableName());
            List<ColumnClass> columnClassList = new ArrayList<>();
            while (columns.next()) {
                String columName = columns.getString("COLUMN_NAME");
                String typeName = columns.getString("TYPE_NAME");
                String remarks = columns.getString("REMARKS");
                ColumnClass columnClass = new ColumnClass();
                columnClass.setColumnName(columName);
                columnClass.setType(typeName);
                columnClass.setRemark(remarks);
                columnClass.setPropertyName(modelName);
                while (primaryKeys.next()) {
                    String pkName = primaryKeys.getString("COLUMN_NAME");
                    if (pkName.equals(columName)) {
                        columnClass.setPrimary(true);
                    }
                }
                columnClassList.add(columnClass);
            }
            tableClass.setColumns(columnClassList);
            String path = request.getServletContext().getRealPath("/") + "/" + tableClass.getPackageName().replace(".", "/");
            System.out.println(path);
            generate(entityTemplate,tableClass,path);
        }
        return Result.ok("构建成功");
    }

    private void generate(Template template, TableClass tableClass, String path) throws IOException, TemplateException {
        File folder = new File(path);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String fileName = path + "/" + tableClass.getEntityName() + template.getName().replace(".ftl", "");
        FileOutputStream fos = new FileOutputStream(fileName);
        OutputStreamWriter out = new OutputStreamWriter(fos);
        template.process(tableClass,out);
        fos.close();
        out.close();
    }

}
